S08-06 Node-自动化部署、Cookie、Session、token
[TOC]
自动化部署
cookie
Cookie 是一个 HTTP 请求标头,其中含有先前由服务器通过 Set-Cookie
标头投放或通过 JavaScript 的 document.cookie
方法设置,然后存储到客户端的 HTTP cookie 。
语法
Set-Cookie
头部用于在 HTTP 响应中设置 Cookie。包含多个可选参数,允许你精确控制 Cookie 的行为和有效期。
js
Set-Cookie: <cookie-name>=<cookie-value>[; <attribute1>=<value1>][; <attribute2>=<value2>]...
参数:
<cookie-name>=<cookie-value>
:设置的cookie,一次只能设置一个cookie。要设置多个 cookie,则应在同一响应中设置多个Set-Cookie
标头。[; <attribute1>=<value1>][; <attribute2>=<value2>]...
:可选参数,用于精确控制 Cookie 的行为和有效期,通常用分号;
分隔。- Expires:
HTTP-date
,设置 Cookie 的过期时间。如:Expires=Wed, 21 Oct 2025 07:28:00 GMT
。 - Max-Age:
number
,从设置 Cookie 的时间开始,指定 Cookie 的有效秒数。如:Max-Age=3600
。 - Domain:
string
,指定 Cookie 所属的域名。如果不设置,默认为发送 Cookie 的请求的域名。如:Domain=example.com
。 - Path:
string
,指定 Cookie 可用的 URL 路径。如果不设置,默认为发送 Cookie 的请求路径。如:Path=/
(表示整个网站可用)。 - Secure:
void
,指示 Cookie 仅在 HTTPS 连接中发送。 - HttpOnly:
boolean
,指示 Cookie 不能通过 JavaScript 的Document.cookie
访问,提高安全性。 - SameSite:
Strict | Lax | None
,用于控制浏览器在跨站请求时如何处理 Cookie。防止如跨站请求伪造(CSRF)的攻击。Strict
:仅在同站请求时发送 Cookie。Lax
:默认,允许在同站请求和某些跨站请求(例如 GET 请求、点击链接)时发送 Cookie。None
:不限制 Cookie 的发送,跨站请求时也会发送 Cookie。- *注意:*当使用
SameSite=None
时,必须同时设置Secure
属性,以确保 Cookie 仅通过 HTTPS 连接发送。
- *注意:*当使用
- Expires:
注意:
Set-Cookie
是服务器发送 Cookie 的方式,出于安全考虑,浏览器不会暴露此头部给前端代码,但允许通过document.cookie
访问和设置非HttpOnly
的 Cookie。- Cookie的大小限制: 单个 Cookie 的大小通常限制在 4KB 左右,整体数量也有限制(大约 20-50 个)。
- 由于隐私和安全原因,某些浏览器可能对第三方 Cookie 有额外的限制。
示例: 完整的Set-Cookie,使用了所有的属性
js
Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2025 07:28:00 GMT; Max-Age=86400; Domain=example.com; Path=/; Secure; HttpOnly; SameSite=Lax
示例: Set-Cookie设置多个cookie
js
Set-Cookie: name=tom; Expires=Wed, 21 Oct 2025 07:28:00 GMT // name=tom;
Set-Cookie: age=18; Secure; SameSite=None // age=18;
服务端
原生Node
设置:
在原生Node中可以通过 res.setHeader('Set-Cookie', 'key=value; ...options')
设置Cookie。
js
const http = require('http');
const server = http.createServer((req, res) => {
// 设置 Cookie
res.setHeader('Set-Cookie', 'username=JohnDoe; HttpOnly; Max-Age=3600'); // 有效期 1 小时
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Cookie has been set');
});
server.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
获取:
在原生 Node.js 中,可以通过 req.headers.cookie
获取cookie,但此时获取到的是cookie字符串,你需要手动解析请求头中的 Cookie:
js
const http = require('http');
const server = http.createServer((req, res) => {
if (req.headers.cookie) {
// 获取并解析cookie
const cookies = req.headers.cookie.split('; ').reduce((acc, cookie) => {
const [key, value] = cookie.split('=');
acc[key] = value;
return acc;
}, {});
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`Username: ${cookies.username}`);
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('No cookies found');
}
});
server.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
Express
设置:
在原生Express中可以通过 res.cookie(key, value, {...options})
设置Cookie。
js
const express = require('express');
const app = express();
app.get('/set-cookie', (req, res) => {
res.cookie('username', 'JohnDoe', { httpOnly: true, maxAge: 3600000 }); // 有效期 1 小时
res.send('Cookie has been set');
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
获取:
在 Express 中,使用 cookie-parser
中间件可以方便地访问 Cookie:
js
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.get('/get-cookie', (req, res) => {
const username = req.cookies.username; // 直接获取 Cookie
res.send(`Username: ${username || 'No cookie found'}`);
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
浏览器
设置:
在浏览器中可以通过document.cookie
设置cookie。
js
document.cookie = "username=JohnDoe; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/; Secure; SameSite=Lax"; // username=JohnDoe;
获取:
在浏览器中可以通过document.cookie
获取cookie。
js
let cookies = document.cookie;
console.log(cookies); // 输出所有 Cookie
删除:
要删除 Cookie,只需设置一个过期日期为过去的时间:
js
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";
session
token
JWT
jwt.sign(payload, privateKey, {expiresIn, algorithm})
:颁发 tokenjwt.verify(token, publicKey, {algorithm})
:验证 token
非对称加密
生成公钥和私钥
使用 openssl
来生成一对私钥和公钥
sh
# 1. 进入到保存公钥和私钥的目录中
cd 保存目录
# 2. 进入SSL的REPL
openssl
# 3. 生成私钥和公钥
genrsa -out private.key 1024 # 生成私钥 private.key
rsa -in private.key -pubout -out public.key # 生成公钥 public.key